Skip to content

release: v0.2.0 — frontend rewrite, ActiveMQ detector, mode=none default, drill-down treemap#112

Merged
aksOps merged 7 commits intomainfrom
release/0.2.0
May 3, 2026
Merged

release: v0.2.0 — frontend rewrite, ActiveMQ detector, mode=none default, drill-down treemap#112
aksOps merged 7 commits intomainfrom
release/0.2.0

Conversation

@aksOps
Copy link
Copy Markdown
Contributor

@aksOps aksOps commented May 3, 2026

Summary

Five topics squashed for the v0.2.0 cut. Tests: 3706 / 0 failures / 0 errors / 32 skipped on the squashed branch.

# Commit Type
1 0c13d26 perf(detectors): quick-reject pre-screen on auth detectors (-31% detector CPU) perf
2 3a82e28 feat(ui): migrate frontend from AntD to @ossrandom/design-system feat
3 d0274f2 fix(auth): allow_unauthenticated bypass actually grants /api access fix
4 aaf7160 feat(auth)!: default mcp.auth.mode=none with allow_unauthenticated=true feat ⚠️ default-changing
5 3391422 feat(messaging): Apache ActiveMQ Classic + Artemis detector feat
6 c46e656 fix(health): make codeiq serve start cleanly under Spring Boot 4 fix

⚠️ Behaviour change — auth default flip

mcp.auth.mode was already none by default but allowUnauthenticated evaluated to false, which made codeiq serve fail-fast on a fresh install. This PR flips the default allowUnauthenticated to true so a clean install boots unauthenticated out of the box. Operators wanting auth in production must opt in explicitly:

# codeiq.yml
mcp:
  auth:
    mode: bearer
    # token via CODEIQ_MCP_TOKEN env or mcp.auth.token field

To preserve the prior fail-fast behaviour without enabling bearer auth, set mcp.auth.allow_unauthenticated: false explicitly. The TokenResolverTest#modeNone_servingProfile_throwsByDefault covers that path and still passes.

Frontend

Full rewrite onto @ossrandom/design-system@0.3.0. AntD + ECharts + @ant-design/icons retired. Surface changes:

  • AppShell header with single IconButton theme toggle + monospace MCP-URL pill (copy-to-clipboard).
  • Stats grid is now a CSS auto-fit grid (mobile responsive).
  • File-tree treemap renders via @ossrandom/design-system/charts, canvas engine, maxDepth=1. Drill-down/up via a breadcrumb row; layout deterministic across page loads.
  • File viewer drawer kept; MCP Tools sidebar removed.
  • Three orphan pages deleted (Explorer.tsx, McpConsole.tsx, CodebaseMap.tsx) — none routed.

ActiveMQ detector

detector/jvm/java/ActiveMqDetector.java covers ActiveMQ Classic + Artemis (disambiguated by import / FQN), all transport URLs incl. failover:(...), named ActiveMQQueue/ActiveMQTopic, session.createQueue/createTopic (only when AMQ context is present — avoids double-counting against JmsDetector), and spring.activemq.broker-url / spring.artemis.broker-url. Same emission shape as IbmMqDetector / TibcoEmsDetector for clean topology composition.

17 new unit tests: metadata, early-exit, Classic + Artemis, named queue/topic producer/consumer, failover/pooled URL variants, Spring Boot config keys, negative double-counting, determinism.

Health / startup fix

Two coupled changes that let java -jar code-iq-cli.jar serve <path> boot from defaults — no -D, no env var, no codeiq.yml:

  • GraphHealthIndicator: @ConditionalOnBean(GraphStore.class)@Profile("serving"). Spring documents @ConditionalOnBean as fragile on user @Components.
  • application.yml: management.endpoint.health.validate-group-membership: false. Spring Boot 4's strict group-membership validation runs before profile-conditional beans register, tripping the readiness include of graphHealthIndicator. Disabled per the error's own remediation hint; missing health contributors are silently skipped at probe time.

Test plan

  • CI green on the new commits
  • Spot-check https://test.randomcodespace.dev/ after merge: stats grid renders, treemap drills in/out via cell click + breadcrumb, MCP-URL pill copies, theme toggle flips
  • Smoke curl http://127.0.0.1:37779/api/stats (no Authorization header) returns the graph stats JSON
  • Confirm curl http://127.0.0.1:37779/actuator/health/readiness returns {"status":"UP"}
  • After this lands, cut v0.2.0b0 via the beta-java.yml workflow, then v0.2.0 via release-java.yml once the beta artifact validates on Sonatype Central

🤖 Generated with Claude Code

aksOps and others added 6 commits April 29, 2026 13:34
…ctor CPU)

Profiling on a 30K-file polyglot fixture (kept at ~/projects/polyglot-bench:
spring-petclinic-microservices, airflow, istio, eShop, angular/components,
nuxt, actix/examples, ktor-samples, nlohmann/json, play-samples,
PSScriptAnalyzer, terraform-aws-eks; 14 distinct languages) showed the three
cross-cutting auth detectors burning 55% of all detector CPU because they
ran the lines × patterns double loop on every supported-language file —
even files with zero auth keywords.

Fix: per-detector PRE_SCREEN Pattern with all distinctive literal substrings
of the underlying patterns. One regex pass over file content; if no keyword
present, the file cannot match — short-circuit before the line loop.

Measured impact (JFR ExecutionSample, JDK 25, polyglot fixture):

  CertificateAuthDetector:  244 → 147 samples  (-39.8%, -0.97s CPU)
  SessionHeaderAuthDetector: 206 →  43 samples  (-79.1%, -1.63s CPU)
  LdapAuthDetector:           47 →  25 samples  (-46.8%, -0.22s CPU)
  Auth subtotal:             497 → 215 samples  (-56.7%, -2.82s)
  All detectors total:       902 → 624 samples  (-30.8%, -2.78s)

Detection semantics unchanged — pre-screen rejects only files where no
underlying pattern can match (keyword absent). Tests covering keyword-bearing
fixtures pass through pre-screen and run the existing logic byte-for-byte.

Tests: 3689 / 0 failures / 0 errors / 32 skipped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Full UI rewrite onto @ossrandom/design-system v0.3.0 (npm). Replaces
Ant Design + ECharts + @ant-design/icons with the design-system
primitives + charts subpath + an inline-SVG icon set.

Surface changes:
- AppShell-based header with a single IconButton theme toggle and a
  monospace MCP-URL pill (copy-to-clipboard).
- Stats grid replaced with a CSS auto-fit grid (mobile-responsive).
- File-tree treemap renders via @ossrandom/design-system/charts
  (d3-hierarchy, canvas engine, maxDepth=1) with an explicit drill-down
  / drill-up affordance via a breadcrumb row; treemap layout is
  deterministic (children sorted alphabetically, fixed height, single
  remount via key when focusPath changes).
- File viewer drawer kept; MCP Tools sidebar removed (the design-system
  Menu's nested-inline expansion didn't match the prior UX).
- Three orphan pages deleted (Explorer.tsx, McpConsole.tsx,
  CodebaseMap.tsx) — none were routed in App.tsx.
- index.css trimmed to body reset + layout-only classes using
  design-system CSS tokens; `.rcs-treemap-engine-badge` hidden via a
  single rule.
- vite.config.ts: manualChunks reorganised
  (vendor-ds / vendor-ds-charts replace vendor-antd / vendor-echarts).

Bundled fonts and the deck.gl tesselator chunk live alongside the
hashed JS in src/main/resources/static/assets/ — air-gapped requirement
per build.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When `mcp.auth.mode=none` AND `allow_unauthenticated=true`, the filter
used to call chain.doFilter(...) without setting an Authentication on
the SecurityContext. The SecurityFilterChain has

    .requestMatchers("/api/**", "/mcp/**", "/actuator/**").authenticated()
    .anonymous().disable()

so requests reaching the controllers without a Principal were rejected
with 403 — the "unauthenticated" escape hatch was inert. Bypass branch
now installs a fake PreAuthenticatedAuthenticationToken with role
ROLE_MCP_CLIENT (mirroring the bearer-success path) and clears the
context in finally, so the chain's authenticated() rule passes.

Behavioural impact only when allow_unauthenticated=true; bearer mode
unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Built-in defaults now produce a server that starts unauthenticated out
of the box. The fail-fast safety valve still works: explicitly setting
mcp.auth.allow_unauthenticated=false in codeiq.yml (or env) makes
mode=none refuse to start under the serving profile.

ConfigDefaults previously emitted

    new McpAuthConfig("none", "CODEIQ_MCP_TOKEN", null, null)

which evaluated to allowUnauthenticated=false at runtime; combined with
TokenResolver's serving-profile gate, this hard-failed every fresh
install on `codeiq serve`. Operators wanting auth in production opt in
explicitly via mode=bearer (and CODEIQ_MCP_TOKEN env var).

McpAuthConfig javadoc updated to document the new default semantics:
allow_unauthenticated is now an opt-in *harden* flag (set false to
reject mode=none) rather than an opt-in *escape hatch*.

BREAKING (defaults): a fresh install no longer prompts for or enforces
a token. Upgraded deployments that already set mode=bearer in
codeiq.yml are unaffected. To preserve the prior fail-fast behaviour,
set mcp.auth.allow_unauthenticated: false explicitly.

Tests: TokenResolverTest, ConfigDefaultsTest, ServingChainIntegrationTest,
UnifiedConfigAdapterTest — 27/27 pass. Full suite: 3706 / 0 / 32.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds io.github.randomcodespace.iq.detector.jvm.java.ActiveMqDetector
covering both ActiveMQ Classic (org.apache.activemq.*) and ActiveMQ
Artemis (org.apache.activemq.artemis.*). Both products ship a class
literally named ActiveMQConnectionFactory, so the broker flavour is
disambiguated by import / FQN before emission.

Coverage:
- Connection factories: ActiveMQConnectionFactory,
  ActiveMQQueueConnectionFactory, ActiveMQTopicConnectionFactory,
  ActiveMQJMSConnectionFactory, ActiveMQXAConnectionFactory,
  PooledConnectionFactory.
- Transport URLs: tcp/ssl/nio/udp/vm/amqp/stomp/mqtt/ws/wss with the
  optional +nio / +ssl modifiers, plus failover:(...) / failover:tcp:...
  (the failover transport uses `:(` rather than `://`, handled as a
  separate alternation in BROKER_URL_RE).
- Direct destination instantiation: new ActiveMQQueue("..."),
  new ActiveMQTopic("...").
- session.createQueue("...") / session.createTopic("...") only
  attributed to ActiveMQ when the file already mentions an AMQ import
  or class ref — avoids double-counting against JmsDetector.
- Spring Boot config keys: spring.activemq.broker-url and
  spring.artemis.broker-url in application.properties / application.yml
  (no class context — emits the broker MESSAGE_QUEUE node only).

Emits NodeKind {MESSAGE_QUEUE, QUEUE, TOPIC} with broker properties
("activemq" or "activemq_artemis"), plus EdgeKind
{CONNECTS_TO, SENDS_TO, RECEIVES_FROM} — same shape as IbmMqDetector
and TibcoEmsDetector so the topology view composes cleanly.

Tests: 17 cases covering metadata, early-exit, Classic + Artemis,
named queue/topic producer/consumer, transport URL variants
(failover, pooled), Spring Boot config keys, negative
double-counting against JmsDetector, and a determinism fixture.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two coupled changes that together let `serve` boot from defaults
without -D / env / config overrides.

1. GraphHealthIndicator: @ConditionalOnBean(GraphStore.class) →
   @Profile("serving"). Spring documents @ConditionalOnBean as fragile
   on user @component classes (its evaluation depends on bean-definition
   ordering during scan). The serving profile already guarantees
   GraphStore is present; @Profile activates earlier and deterministic-
   ally so the readiness-group reference resolves on a clean install.

2. application.yml: management.endpoint.health.validate-group-membership
   set to false. Spring Boot 4 enabled strict group-membership validation
   by default — startup fails when a `health.group.*.include` references
   a profile-conditional bean that hasn't yet been added to the registry
   when the management endpoint config loads. The serving profile's
   readiness include of `graphHealthIndicator` consistently tripped this.
   Disabled per the error message's own remediation hint; missing health
   contributors are silently skipped at probe time, which is the desired
   runtime behaviour.

Verified: `java -jar code-iq-cli.jar serve <path> -p 37779` with no
flags / env / codeiq.yml — port binds, /api/stats returns data without
auth, /actuator/health/readiness returns {"status":"UP"}.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 3, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​react-router-dom@​7.14.0 ⏵ 7.14.21001006596100
Updatednpm/​@​axe-core/​playwright@​4.11.1 ⏵ 4.11.3100 +110010099 +170
Addednpm/​@​ossrandom/​design-system@​0.3.07710010091100
Addednpm/​d3-hierarchy@​3.1.210010010082100

View full report

The previous lockfile pointed @ossrandom/design-system at a local
filesystem path (`file:../../../../design-system`, link:true) — a
holdover from the local-checkout development of the design-system.
On CI that path doesn't exist, so `npm install` left the dep
unresolved and `vite build` failed with TS2307 "Cannot find module
'@ossrandom/design-system'".

Regenerated lockfile resolves to the published 0.3.0 tarball:

    https://registry.npmjs.org/@ossrandom/design-system/-/design-system-0.3.0.tgz

Verified locally: `rm -rf node_modules && npm install` clean,
`npm run build` produces the same bundle modulo content-hash filenames.
The two new design-system-*.js chunks reflect the registry-resolved
artifact.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aksOps aksOps merged commit 4b7cb45 into main May 3, 2026
13 checks passed
@aksOps aksOps deleted the release/0.2.0 branch May 3, 2026 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant